// Last Update:2014-08-08 11:00:50
/**
 * @file udp_server.cpp
 * @brief 
 * @author zealoussnow@163.com
 * @version 0.1.00
 * @date 2014-08-07
 */

#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

#include <iostream>
#include "udp_server.h"

UdpServer::UdpServer()
{
    m_socket = -1;
}

UdpServer::~UdpServer()
{
    if(m_socket != -1)
    {
        close(m_socket);
    }
}

bool UdpServer::Init(uint16_t port)
{
    struct sockaddr_in6 listenAddr;
    memset((void *)&listenAddr, 0, sizeof(sockaddr_in));
    listenAddr.sin6_family = AF_INET6;
    listenAddr.sin6_port = htons(port);

    m_socket = socket(AF_INET6, SOCK_DGRAM, 0);
    if(m_socket == -1)
    {
        printf("%s\n", strerror(errno));
        return false;
    }

    if(bind(m_socket, (sockaddr *)&listenAddr, sizeof(sockaddr_in6)) != 0)
    {
        printf("%s\n", strerror(errno));
        return false;
    }

    return true;

}

uint32_t UdpServer::Recv(void *buf, uint32_t size, in6_addr *clientIp, uint16_t *clientPort)
{
    if(m_socket == -1)
    {
        return 0;
    }

    struct sockaddr_in6 clientAddr;
    memset((char *)&clientAddr, 0, sizeof(sockaddr_in6));

    socklen_t clientAddrLength = sizeof(sockaddr_in6);

    int32_t ret = recvfrom(m_socket, buf, size, 0, (sockaddr *)&clientAddr, &clientAddrLength);
    if(ret == -1)
    {
        printf("%s\n", strerror(errno));
        return 0;
    }

    char ipv6[48];
    memset(ipv6, 0, sizeof(ipv6));

    inet_ntop(AF_INET6, &clientAddr.sin6_addr, ipv6, sizeof(ipv6));
    std::cout << "ipv6: " << ipv6 << std::endl;
    memcpy(clientIp, &clientAddr.sin6_addr.s6_addr, 16 * sizeof(uint8_t));
    *clientPort = clientAddr.sin6_port;

    return ret;
}

#if 0
bool UdpServer::Send(const void *buf, uint32_t size, uint32_t clientIp, uint16_t clientPort)
{
    if(m_socket == -1)
    {
        return false;
    }

    struct sockaddr_in clientAddr;
    memset((char *)&clientAddr, 0, sizeof(sockaddr_in));
    clientAddr.sin_addr.s_addr = clientIp;
    clientPort = clientAddr.sin_port = clientPort;
    socklen_t clientAddrLength = 0;

    ssize_t ret = sendto(m_socket, buf, size, 0, (sockaddr *)&clientAddr, clientAddrLength);
    if(ret == -1)
    {
        printf("%s\n", strerror(errno));
        return false;
    }

    return true;
}
#endif
